home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 June / Chip_2002-06_cd1.bin / zkuste / delphi / kolekce / d6 / rxlibsetup.exe / {app} / units / SBEDIT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-02-19  |  27.6 KB  |  979 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 2001,2002 SGB Software          }
  6. {         Copyright (c) 1997, 1998 Fedor Koshevnikov,   }
  7. {                        Igor Pavluk and Serge Korolev  }
  8. {                                                       }
  9. {*******************************************************}
  10.  
  11.  
  12. unit SbEdit;
  13.  
  14. {$I RX.INC}
  15.  
  16. interface
  17.  
  18. uses
  19.   Windows, RTLConsts, DesignIntf, DesignWindows, DesignEditors, VCLEditors,
  20.   SysUtils, Messages, Classes, Graphics, Controls, Forms, Dialogs,
  21.   StdCtrls, Buttons, Grids, SpeedBar,  Menus, Placemnt, RxConst, RxCtrls, VCLUtils;
  22.  
  23. type
  24.  
  25. { TSpeedbarEditor }
  26.  
  27.   TSelectData = record
  28.     bRowCount: Integer;
  29.     bRow: Integer;
  30.     sRowCount: Integer;
  31.     sRow: Integer;
  32.   end;
  33.  
  34.   TSpeedbarEditor = class(TDesignWindow)
  35.     SectionsBox: TGroupBox;
  36.     NewSection: TButton;
  37.     DelSection: TButton;
  38.     ButtonsBox: TGroupBox;
  39.     UpBtn: TSpeedButton;
  40.     DownBtn: TSpeedButton;
  41.     AddButton: TButton;
  42.     RemoveButton: TButton;
  43.     CloseBtn: TButton;
  44.     SectionName: TEdit;
  45.     SectionNameLabel: TLabel;
  46.     SectionList: TDrawGrid;
  47.     ButtonsList: TDrawGrid;
  48.     LabelHint: TLabel;
  49.     PopupMenu: TPopupMenu;
  50.     CopyMenu: TMenuItem;
  51.     PasteMenu: TMenuItem;
  52.     CutMenu: TMenuItem;
  53.     FormPlacement1: TFormPlacement;
  54.     procedure DelSectionClick(Sender: TObject);
  55.     procedure AddButtonClick(Sender: TObject);
  56.     procedure RemoveButtonClick(Sender: TObject);
  57.     procedure CloseBtnClick(Sender: TObject);
  58.     procedure UpBtnClick(Sender: TObject);
  59.     procedure DownBtnClick(Sender: TObject);
  60.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  61.     procedure SectionNameExit(Sender: TObject);
  62.     procedure SectionListSelectCell(Sender: TObject; Col, Row: Longint;
  63.       var CanSelect: Boolean);
  64.     procedure SectionListDrawCell(Sender: TObject; Col, Row: Longint;
  65.       Rect: TRect; State: TGridDrawState);
  66.     procedure ButtonsListDblClick(Sender: TObject);
  67.     procedure ButtonsListKeyDown(Sender: TObject; var Key: Word;
  68.       Shift: TShiftState);
  69.     procedure ButtonsListMouseDown(Sender: TObject; Button: TMouseButton;
  70.       Shift: TShiftState; X, Y: Integer);
  71.     procedure ButtonsListMouseMove(Sender: TObject; Shift: TShiftState; X,
  72.       Y: Integer);
  73.     procedure ButtonsListMouseUp(Sender: TObject; Button: TMouseButton;
  74.       Shift: TShiftState; X, Y: Integer);
  75.     procedure ButtonsListSelectCell(Sender: TObject; Col, Row: Longint;
  76.       var CanSelect: Boolean);
  77.     procedure FormCreate(Sender: TObject);
  78.     procedure FormDestroy(Sender: TObject);
  79.     procedure NewSectionClick(Sender: TObject);
  80.     procedure SectionNameKeyDown(Sender: TObject; var Key: Word;
  81.       Shift: TShiftState);
  82.     procedure ButtonsListDrawCell(Sender: TObject; Col, Row: Longint;
  83.       Rect: TRect; State: TGridDrawState);
  84.     procedure SectionListMouseDown(Sender: TObject; Button: TMouseButton;
  85.       Shift: TShiftState; X, Y: Integer);
  86.     procedure SectionListDragDrop(Sender, Source: TObject; X, Y: Integer);
  87.     procedure SectionListDragOver(Sender, Source: TObject; X, Y: Integer;
  88.       State: TDragState; var Accept: Boolean);
  89.     procedure SectionListKeyDown(Sender: TObject; var Key: Word;
  90.       Shift: TShiftState);
  91.     procedure CopyMenuClick(Sender: TObject);
  92.     procedure PasteMenuClick(Sender: TObject);
  93.     procedure CutMenuClick(Sender: TObject);
  94.     procedure FormShow(Sender: TObject);
  95.   private
  96.     { Private declarations }
  97.     FButton: TBtnControl;
  98.     FImage: TButtonImage;
  99.     FBar: TSpeedBar;
  100.     FDrag: Boolean;
  101.     FDragItem: TSpeedItem;
  102.     FLocked: Integer;
  103.     FSelectData: TSelectData;
  104.     procedure Copy;
  105.     procedure Cut;
  106.     procedure Paste;
  107.     procedure OnPasteItem(Item: TObject);
  108.     procedure SaveSelection;
  109.     procedure RestoreSelection;
  110.     procedure SelectButton(Section: Integer; Item: TSpeedItem; SelectBar: Boolean);
  111.     procedure UpdateEnabled(BtnRow, Section: Integer);
  112.     function CheckSpeedBar: Boolean;
  113.     function ConfirmDelete: Boolean;
  114.     function CurrentSection: Integer;
  115.     function GetForm: TCustomForm;
  116.     procedure SetSection(Section: Integer);
  117.     procedure UpdateData;
  118.     procedure UpdateListHeight;
  119.     procedure SetSpeedBar(Value: TSpeedBar);
  120.     function ItemByRow(Row: Integer): TSpeedItem;
  121.     function SectionByRow(Row: Integer): TSpeedbarSection;
  122.     function ItemBySectionRow(Section, Row: Integer): TSpeedItem;
  123.     procedure CMSpeedBarChanged(var Message: TMessage); message CM_SPEEDBARCHANGED;
  124.   protected
  125.     procedure Activated; override;
  126.     function UniqueName(Component: TComponent): string; override;
  127.   public
  128.     { Public declarations }
  129.     procedure ItemsModified(const Designer : IDesigner); override;
  130.     procedure DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean); override;
  131.     function GetEditState: TEditState; override;
  132.     function EditAction(Action: TEditAction) : Boolean; override;
  133.     property SpeedBar: TSpeedBar read FBar write SetSpeedBar;
  134.     property OwnerForm: TCustomForm read GetForm;
  135.   end;
  136.  
  137. { TSpeedbarCompEditor }
  138.  
  139.   TSpeedbarCompEditor = class(TComponentEditor)
  140.     procedure ExecuteVerb(Index: Integer); override;
  141.     function GetVerb(Index: Integer): string; override;
  142.     function GetVerbCount: Integer; override;
  143.   end;
  144.  
  145. implementation
  146.  
  147. uses TypInfo, MaxMin, RXLConst, RxProps, RxDsgn;
  148.  
  149. {$R *.DFM}
  150.  
  151. {$IFDEF WIN32}
  152.  {$D-}
  153. {$ENDIF}
  154.  
  155. {$IFDEF RX_D4}
  156. type
  157.   TDesigner = IDesigner;
  158.   TFormDesigner = IDesigner;
  159. {$ENDIF}
  160.  
  161. { Utility routines }
  162.  
  163. function FindEditor(Speedbar: TSpeedbar): TSpeedbarEditor;
  164. var
  165.   I: Integer;
  166. begin
  167.   Result := nil;
  168.   for I := 0 to Screen.FormCount - 1 do begin
  169.     if Screen.Forms[I] is TSpeedbarEditor then begin
  170.       if TSpeedbarEditor(Screen.Forms[I]).SpeedBar = SpeedBar then
  171.       begin
  172.         Result := TSpeedbarEditor(Screen.Forms[I]);
  173.         Break;
  174.       end;
  175.     end;
  176.   end;
  177. end;
  178.  
  179. procedure ShowSpeedbarDesigner(Designer: TDesigner; Speedbar: TSpeedbar);
  180. var
  181.   Editor: TSpeedbarEditor;
  182. begin
  183.   if Speedbar = nil then Exit;
  184.   Editor := FindEditor(Speedbar);
  185.   if Editor <> nil then begin
  186.     Editor.Show;
  187.     if Editor.WindowState = wsMinimized then Editor.WindowState := wsNormal;
  188.   end
  189.   else begin
  190.     Editor := TSpeedbarEditor.Create(Application);
  191.     try
  192.       Editor.Designer := TFormDesigner(Designer);
  193.       Editor.Speedbar := Speedbar;
  194.       Editor.Show;
  195.     except
  196.       Editor.Free;
  197.       raise;
  198.     end;
  199.   end;
  200. end;
  201.  
  202. { TSpeedbarCompEditor }
  203.  
  204. procedure TSpeedbarCompEditor.ExecuteVerb(Index: Integer);
  205. begin
  206.   case Index of
  207.     0: ShowSpeedbarDesigner(Designer, TSpeedbar(Component));
  208.   end;
  209. end;
  210.  
  211. function TSpeedbarCompEditor.GetVerb(Index: Integer): string;
  212. begin
  213.   case Index of
  214.     0: Result := LoadStr(srSpeedbarDesigner);
  215.   end;
  216. end;
  217.  
  218. function TSpeedbarCompEditor.GetVerbCount: Integer;
  219. begin
  220.   Result := 1;
  221. end;
  222.  
  223. { TSpeedbarEditor }
  224.  
  225. const
  226.   MaxBtnListHeight = 158;
  227.  
  228. function TSpeedbarEditor.UniqueName(Component: TComponent): string;
  229. var
  230.   Temp: string;
  231. begin
  232.   Result := '';
  233.   if (Component <> nil) then Temp := Component.ClassName
  234.   else Temp := TSpeedItem.ClassName;
  235.   if (UpCase(Temp[1]) = 'T') and (Length(Temp) > 1) then
  236.     System.Delete(Temp, 1, 1);
  237.   Result := Designer.UniqueName(Temp);
  238. end;
  239.  
  240. function TSpeedbarEditor.GetEditState: TEditState;
  241. begin
  242.   Result := [];
  243.   if RemoveButton.Enabled then begin
  244.     Result := [esCanDelete, esCanCut, esCanCopy];
  245.   end;
  246.   if AddButton.Enabled and ClipboardComponents then
  247.     Include(Result, esCanPaste);
  248. end;
  249.  
  250. function TSpeedbarEditor.EditAction(Action: TEditAction) : Boolean;
  251. begin
  252.   Result := True;
  253.   case Action of
  254.     eaCut: Cut;
  255.     eaCopy: Copy;
  256.     eaPaste: Paste;
  257.     eaDelete: RemoveButtonClick(Self);
  258.   end;
  259. end;
  260.  
  261. procedure TSpeedbarEditor.SelectButton(Section: Integer; Item: TSpeedItem;
  262.   SelectBar: Boolean);
  263. var
  264.   FCompList: IDesignerSelections;
  265.   Sect: TSpeedbarSection;
  266. begin
  267.   if CheckSpeedBar and Active then begin
  268.     //Designer.GetSelections(FCompList);
  269.     FCompList := CreateSelectionList;
  270.     if not SelectBar then begin
  271.       if (ActiveControl = SectionList) or (ActiveControl = SectionName) then
  272.       begin
  273.         Sect := SectionByRow(Section);
  274.         if Sect <> nil then FCompList.Add(Sect);
  275.       end;
  276.       if (FCompList.Count = 0) and (Item <> nil) then FCompList.Add(Item);
  277.     end;
  278.     if (FBar <> nil) and (FCompList.Count = 0) then FCompList.Add(FBar);
  279.     SetSelection(FCompList);
  280.   end;
  281. end;
  282.  
  283. procedure TSpeedbarEditor.DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean);
  284. begin
  285.   if ADesigner.Root = OwnerForm then Free;
  286. end;
  287.  
  288. procedure TSpeedbarEditor.ItemsModified(const Designer : IDesigner);
  289. begin
  290.   if not (csDestroying in ComponentState) then UpdateData;
  291. end;
  292.  
  293. procedure TSpeedbarEditor.Activated;
  294. begin
  295.   SelectButton(CurrentSection, ItemByRow(ButtonsList.Row), False);
  296.   PasteMenu.Enabled := CheckSpeedBar and (FBar.SectionCount > 0) and
  297.     ClipboardComponents;
  298. end;
  299.  
  300. function TSpeedbarEditor.ConfirmDelete: Boolean;
  301. begin
  302.   Result := MessageDlg(LoadStr(srConfirmSBDelete), mtWarning, mbYesNoCancel, 0) = mrYes;
  303. end;
  304.  
  305. procedure TSpeedbarEditor.SaveSelection;
  306. begin
  307.   with FSelectData do begin
  308.     bRowCount := ButtonsList.RowCount;
  309.     bRow := ButtonsList.Row;
  310.     sRowCount := SectionList.RowCount;
  311.     sRow := SectionList.Row;
  312.   end;
  313. end;
  314.  
  315. procedure TSpeedbarEditor.RestoreSelection;
  316. var
  317.   NewSRow, NewBRow: Integer;
  318. begin
  319.   NewSRow := FSelectData.sRow;
  320.   if (SectionList.RowCount > FSelectData.sRowCount) or
  321.     (NewSRow > SectionList.RowCount - 1) then
  322.     NewSRow := SectionList.RowCount - 1;
  323.   if NewSRow < 0 then NewSRow := 0;
  324.   SectionList.Row := NewSRow;
  325.   SetSection(SectionList.Row); { set ButtonsList to current section }
  326.   NewBRow := FSelectData.bRow;
  327.   if (ButtonsList.RowCount > FSelectData.bRowCount) or
  328.     (NewBRow > ButtonsList.RowCount - 1) then
  329.     NewBRow := ButtonsList.RowCount - 1;
  330.   if NewBRow < 0 then NewBRow := 0;
  331.   ButtonsList.Row := NewBRow;
  332. end;
  333.  
  334. procedure TSpeedbarEditor.UpdateEnabled(BtnRow, Section: Integer);
  335. var
  336.   EnableSect, EnableBtn: Boolean;
  337. begin
  338.   EnableSect := CheckSpeedBar and (FBar.SectionCount > 0);
  339.   EnableBtn := EnableSect and (BtnRow >= 0) and (ItemBySectionRow(Section,
  340.     BtnRow) <> nil);
  341.   DelSection.Enabled := EnableSect;
  342.   SectionName.Enabled := EnableSect;
  343.   AddButton.Enabled := EnableSect;
  344.   RemoveButton.Enabled := EnableBtn;
  345.   CopyMenu.Enabled := EnableBtn;
  346.   CutMenu.Enabled := EnableBtn;
  347.   PasteMenu.Enabled := EnableSect and ClipboardComponents;
  348.   UpBtn.Enabled := EnableBtn and (BtnRow > 0);
  349.   DownBtn.Enabled := EnableBtn and (BtnRow < ButtonsList.RowCount - 1);
  350. end;
  351.  
  352. function TSpeedbarEditor.CheckSpeedBar: Boolean;
  353. begin
  354.   Result := (FBar <> nil) and (FBar.Owner <> nil) and (FBar.Parent <> nil)
  355.     and (Designer.Root <> nil);
  356. end;
  357.  
  358. function TSpeedbarEditor.CurrentSection: Integer;
  359. begin
  360.   if CheckSpeedBar and (FBar.SectionCount > 0) then
  361.     Result := SectionList.Row
  362.   else Result := -1;
  363. end;
  364.  
  365. procedure TSpeedbarEditor.SetSection(Section: Integer);
  366. var
  367.   I: Integer;
  368. begin
  369.   if CheckSpeedBar then begin
  370.     I := Section;
  371.     if (I >= 0) and (I < FBar.SectionCount) then begin
  372.       SectionName.Text := TSpeedbarSection(FBar.Sections[I]).Caption;
  373.       ButtonsList.RowCount := FBar.ItemsCount(I);
  374.     end
  375.     else begin
  376.       SectionName.Text := '';
  377.       ButtonsList.RowCount := 0;
  378.     end;
  379.     SectionList.DefaultColWidth := SectionList.ClientWidth;
  380.     ButtonsList.DefaultColWidth := ButtonsList.ClientWidth;
  381.   end;
  382. end;
  383.  
  384. procedure TSpeedbarEditor.UpdateData;
  385. begin
  386.   Inc(FLocked);
  387.   try
  388.     SaveSelection;
  389.     if CheckSpeedBar then SectionList.RowCount := FBar.SectionCount
  390.     else SectionList.RowCount := 0;
  391.     RestoreSelection; { set section }
  392.   finally
  393.     Dec(FLocked);
  394.   end;
  395.   UpdateEnabled(ButtonsList.Row, SectionList.Row);
  396.   SelectButton(CurrentSection, ItemByRow(ButtonsList.Row), False);
  397. end;
  398.  
  399. function TSpeedbarEditor.GetForm: TCustomForm;
  400. begin
  401.   Result := TCustomForm(Designer.Root); { GetParentForm(FBar) }
  402. end;
  403.  
  404. procedure TSpeedbarEditor.UpdateListHeight;
  405. var
  406.   Cnt: Integer;
  407.   MaxHeight: Integer;
  408. begin
  409.   Canvas.Font := Font;
  410.   MaxHeight := MulDiv(MaxBtnListHeight, Screen.PixelsPerInch, 96);
  411.   ButtonsList.DefaultRowHeight := FBar.BtnHeight + 2;
  412.   Cnt := Max(1, Max(ButtonsList.ClientHeight, MaxHeight) div
  413.     (FBar.BtnHeight + 2));
  414.   ButtonsList.ClientHeight := Min(ButtonsList.DefaultRowHeight * Cnt,
  415.     MaxHeight);
  416.   SectionList.DefaultRowHeight := Canvas.TextHeight('Wg') + 2;
  417. end;
  418.  
  419. procedure TSpeedbarEditor.SetSpeedBar(Value: TSpeedBar);
  420. var
  421.   I: Integer;
  422. begin
  423.   if FBar <> Value then begin
  424.     if FBar <> nil then FBar.SetEditing(0);
  425.     FBar := Value;
  426.     if FBar <> nil then FBar.SetEditing(Handle);
  427.     Inc(FLocked);
  428.     try
  429.       if FBar <> nil then UpdateListHeight;
  430.       if FBar.SectionCount = 0 then NewSectionClick(Self)
  431.       else
  432.         for I := 0 to FBar.SectionCount - 1 do begin
  433.           if FBar.Sections[I].Name = '' then begin
  434.             FBar.Sections[I].Name := UniqueName(FBar.Sections[I]);
  435.             Designer.Modified;
  436.           end;
  437.         end;
  438.       if ButtonsList.RowCount > 0 then ActiveControl := ButtonsList
  439.       else ActiveControl := SectionList;
  440.       UpdateData;
  441.       ButtonsList.Row := 0;
  442.     finally
  443.       Dec(FLocked);
  444.     end;
  445.     SectionList.Row := 0;
  446.   end;
  447. end;
  448.  
  449. procedure TSpeedbarEditor.CMSpeedBarChanged(var Message: TMessage);
  450. begin
  451.   if Pointer(Message.LParam) = FBar then begin
  452.     case Message.WParam of
  453.       SBR_CHANGED: Designer.Modified;
  454.       SBR_DESTROYED: Close;
  455.       SBR_BTNSIZECHANGED: if FBar <> nil then UpdateListHeight;
  456.     end;
  457.   end
  458.   else if (Message.WParam = SBR_BTNSELECT) and CheckSpeedBar then begin
  459.     SelectButton(-1, nil, True);
  460.     Designer.Modified;
  461.   end;
  462. end;
  463.  
  464. function TSpeedbarEditor.ItemBySectionRow(Section, Row: Integer): TSpeedItem;
  465. begin
  466.   if CheckSpeedBar then Result := FBar.Items(Section, Row)
  467.   else Result := nil;
  468. end;
  469.  
  470. function TSpeedbarEditor.SectionByRow(Row: Integer): TSpeedbarSection;
  471. begin
  472.   if CheckSpeedBar and (Row >= 0) and (Row < FBar.SectionCount) then
  473.     Result := FBar.Sections[Row]
  474.   else Result := nil;
  475. end;
  476.  
  477. function TSpeedbarEditor.ItemByRow(Row: Integer): TSpeedItem;
  478. begin
  479.   Result := ItemBySectionRow(CurrentSection, Row);
  480. end;
  481.  
  482. procedure TSpeedbarEditor.NewSectionClick(Sender: TObject);
  483. var
  484.   S: string;
  485.   I: Integer;
  486. begin
  487.   if CheckSpeedBar then begin
  488.     I := 0;
  489.     repeat
  490.       S := Format(LoadStr(srNewSectionName), [I]);
  491.       Inc(I);
  492.     until FBar.SearchSection(S) < 0;
  493.     I := NewSpeedSection(FBar, S);
  494.     if I >= 0 then FBar.Sections[I].Name := UniqueName(FBar.Sections[I]);
  495.     ActiveControl := SectionName;
  496.     Designer.Modified;
  497.   end;
  498. end;
  499.  
  500. procedure TSpeedbarEditor.DelSectionClick(Sender: TObject);
  501. var
  502.   Sect: Integer;
  503.   Item: TSpeedItem;
  504. begin
  505.   if CheckSpeedBar and ConfirmDelete then begin
  506.     Sect := SectionList.Row;
  507.     if (Sect >= 0) and (Sect < FBar.SectionCount) then begin
  508.       Self.ValidateRename(FBar.Sections[Sect],
  509.         FBar.Sections[Sect].Name, '');
  510.       try
  511.         while FBar.ItemsCount(Sect) > 0 do begin
  512.           Item := FBar.Items(Sect, 0);
  513.           if Item <> nil then begin
  514.             OwnerForm.RemoveComponent(Item);
  515.             Item.Free;
  516.           end;
  517.         end;
  518.         FBar.RemoveSection(Sect);
  519.       finally
  520.         Designer.Modified;
  521.       end;
  522.     end;
  523.   end;
  524. end;
  525.  
  526. procedure TSpeedbarEditor.Copy;
  527. var
  528.   CompList: IDesignerSelections;
  529.   Item: TSpeedItem;
  530. begin
  531.   CompList := CreateSelectionList;
  532.   try
  533.     Item := ItemByRow(ButtonsList.Row);
  534.     if Item <> nil then begin
  535.       Item.InvalidateItem;
  536.       CompList.Add(Item);
  537.       CopyComponents(OwnerForm, CompList);
  538.       Item.UpdateSection;
  539.     end;
  540.   finally
  541.     //CompList.Free;
  542.   end;
  543. end;
  544.  
  545. procedure TSpeedbarEditor.Paste;
  546. var
  547.   CompList: IDesignerSelections;
  548. begin
  549.   if CheckSpeedBar then begin
  550.     CompList := CreateSelectionList;
  551.     try
  552.       FBar.OnAddItem := OnPasteItem;
  553.       try
  554.         PasteComponents(OwnerForm, FBar, CompList);
  555.       finally
  556.         FBar.OnAddItem := nil;
  557.       end;
  558.       UpdateData;
  559.     finally
  560.       //CompList.Free;
  561.     end;
  562.   end;
  563. end;
  564.  
  565. procedure TSpeedbarEditor.Cut;
  566. begin
  567.   Copy;
  568.   RemoveButtonClick(Self);
  569. end;
  570.  
  571. procedure TSpeedbarEditor.OnPasteItem(Item: TObject);
  572. begin
  573.   if (Item <> nil) then begin
  574.     if CheckSpeedBar and (Item is TSpeedItem) then begin
  575.       TSpeedItem(Item).ASection := CurrentSection;
  576.       TSpeedItem(Item).Visible := False;
  577.     end
  578.   end;
  579. end;
  580.  
  581. procedure TSpeedbarEditor.AddButtonClick(Sender: TObject);
  582. var
  583.   I: Integer;
  584.   Item: TSpeedItem;
  585. begin
  586.   I := CurrentSection;
  587.   if I < 0 then Exit;
  588.   Item := TSpeedItem.Create(OwnerForm);
  589.   if Item <> nil then
  590.     try
  591.       FBar.AddItem(I, Item);
  592.       Item.Name := UniqueName(Item);
  593.       Designer.Modified;
  594.       if (Sender <> nil) then ActivateInspector(#0);
  595.     except
  596.       Item.Free;
  597.       raise;
  598.     end
  599.   else raise ESpeedbarError.CreateRes(srSBItemNotCreate);
  600. end;
  601.  
  602. procedure TSpeedbarEditor.RemoveButtonClick(Sender: TObject);
  603. var
  604.   Item: TSpeedItem;
  605. begin
  606.   Item := ItemByRow(ButtonsList.Row);
  607.   if Item <> nil then begin
  608.     Self.ValidateRename(Item, Item.Name, '');
  609.     OwnerForm.RemoveComponent(Item);
  610.     Item.Free;
  611.     Designer.Modified;
  612.   end;
  613. end;
  614.  
  615. procedure TSpeedbarEditor.CloseBtnClick(Sender: TObject);
  616. begin
  617.   Close;
  618. end;
  619.  
  620. procedure TSpeedbarEditor.UpBtnClick(Sender: TObject);
  621. var
  622.   I, Sect: Integer;
  623. begin
  624.   if CheckSpeedBar and FBar.FindItem(ItemByRow(ButtonsList.Row), Sect, I) then
  625.   begin
  626.     if I > 0 then begin
  627.       FBar.Sections[Sect].List.Move(I, I - 1);
  628.       Designer.Modified;
  629.       ButtonsList.Invalidate;
  630.       ButtonsList.Row := ButtonsList.Row - 1;
  631.     end;
  632.   end;
  633. end;
  634.  
  635. procedure TSpeedbarEditor.DownBtnClick(Sender: TObject);
  636. var
  637.   I, Sect: Integer;
  638. begin
  639.   if CheckSpeedBar and FBar.FindItem(ItemByRow(ButtonsList.Row), Sect, I) then
  640.   begin
  641.     if I < FBar.ItemsCount(Sect) - 1 then begin
  642.       FBar.Sections[Sect].List.Move(I, I + 1);
  643.       Designer.Modified;
  644.       ButtonsList.Invalidate;
  645.       ButtonsList.Row := ButtonsList.Row + 1;
  646.     end;
  647.   end;
  648. end;
  649.  
  650. procedure TSpeedbarEditor.CopyMenuClick(Sender: TObject);
  651. begin
  652.   Copy;
  653. end;
  654.  
  655. procedure TSpeedbarEditor.PasteMenuClick(Sender: TObject);
  656. begin
  657.   Paste;
  658. end;
  659.  
  660. procedure TSpeedbarEditor.CutMenuClick(Sender: TObject);
  661. begin
  662.   Cut;
  663. end;
  664.  
  665. procedure TSpeedbarEditor.SectionNameExit(Sender: TObject);
  666. var
  667.   I: Integer;
  668. begin
  669.   if CheckSpeedBar and (FBar.SectionCount > 0) then begin
  670.     I := CurrentSection;
  671.     if I >= 0 then begin
  672.       FBar.Sections[I].Caption := SectionName.Text;
  673.       Designer.Modified;
  674.     end;
  675.   end;
  676. end;
  677.  
  678. procedure TSpeedbarEditor.SectionListSelectCell(Sender: TObject; Col,
  679.   Row: Longint; var CanSelect: Boolean);
  680. begin
  681.   CanSelect := False;
  682.   if CheckSpeedBar and (Row < FBar.SectionCount) and (Row >= 0) then begin
  683.     if FLocked = 0 then begin
  684.       SetSection(Row);
  685.       UpdateEnabled(ButtonsList.Row, Row);
  686.       ButtonsList.Invalidate;
  687.       SelectButton(Row, ItemBySectionRow(Row, ButtonsList.Row), False);
  688.     end;
  689.     CanSelect := True;
  690.   end;
  691. end;
  692.  
  693. procedure TSpeedbarEditor.SectionListDrawCell(Sender: TObject; Col,
  694.   Row: Longint; Rect: TRect; State: TGridDrawState);
  695. begin
  696.   if CheckSpeedBar then begin
  697.     if (Row < FBar.SectionCount) and (Row >= 0) then begin
  698.       DrawCellText(Sender as TDrawGrid, Col, Row,
  699.         FBar.Sections[Row].Caption, Rect, taLeftJustify, vaCenter
  700.         {$IFDEF RX_D4}, TDrawGrid(Sender).IsRightToLeft {$ENDIF});
  701.     end;
  702.   end;
  703. end;
  704.  
  705. procedure TSpeedbarEditor.SectionListKeyDown(Sender: TObject;
  706.   var Key: Word; Shift: TShiftState);
  707. begin
  708.   case Key of
  709.     VK_RETURN: if SectionByRow(SectionList.Row) <> nil then ActivateInspector(#0);
  710.     VK_DELETE: DelSectionClick(Self);
  711.     VK_INSERT, VK_ADD: NewSectionClick(Self);
  712.     else Exit;
  713.   end;
  714.   Key := 0;
  715. end;
  716.  
  717. procedure TSpeedbarEditor.ButtonsListKeyDown(Sender: TObject;
  718.   var Key: Word; Shift: TShiftState);
  719. begin
  720.   case Key of
  721.     VK_RETURN: if ItemByRow(ButtonsList.Row) <> nil then ActivateInspector(#0);
  722.     VK_DELETE: RemoveButtonClick(Self);
  723.     VK_INSERT, VK_ADD: AddButtonClick(Self);
  724.     else Exit;
  725.   end;
  726.   Key := 0;
  727. end;
  728.  
  729. procedure TSpeedbarEditor.ButtonsListDblClick(Sender: TObject);
  730. type
  731.   PParamData = ^TParamData;
  732.   TParamData = record
  733.     Flags: TParamFlags;
  734.     ParamNameAndType: array[0..100] of Char;
  735.   end;
  736. const
  737. {$IFDEF CBUILDER}
  738.   sSender: string[7] = '*Sender';
  739. {$ELSE}
  740.   sSender: string[6] = 'Sender';
  741. {$ENDIF}
  742.   sObject: string[7] = 'TObject';
  743. var
  744.   Btn: TSpeedItem;
  745.   I, Num: Integer;
  746.   MethodName: string;
  747.   Method: TMethod;
  748.   TypeData: PTypeData;
  749.   ParamData: PParamData;
  750.   PropInfo: PPropInfo;
  751.   Candidates: TPropInfoList;
  752. begin
  753.   Btn := ItemByRow(ButtonsList.Row);
  754.   if Btn = nil then Exit;
  755.   Candidates := TPropInfoList.Create(Btn, [tkMethod]);
  756.   try
  757.     for I := Candidates.Count - 1 downto 0 do begin
  758.       PropInfo := Candidates[I];
  759.       if CompareText(PropInfo^.Name, 'OnClick') = 0 then begin
  760.         Method := GetMethodProp(Btn, PropInfo);
  761.         MethodName := TFormDesigner(Designer).GetMethodName(Method);
  762.         if MethodName = '' then begin
  763.           MethodName := Btn.Name + 'Click';
  764.           Num := 0;
  765.           while TFormDesigner(Designer).MethodExists(MethodName) do begin
  766.             MethodName := Btn.Name + 'Click' + IntToStr(Num);
  767.             Inc(Num);
  768.           end;
  769.           TypeData := AllocMem(SizeOf(TTypeData));
  770.           try
  771.             TypeData^.MethodKind := mkProcedure;
  772.             TypeData^.ParamCount := 1;
  773.             ParamData := PParamData(@TypeData^.ParamList);
  774.             with ParamData^ do begin
  775.               Flags := [];
  776.               ParamNameAndType[0] := Char(Length(sSender));
  777.               Move(sSender[1], ParamNameAndType[1], Length(sSender));
  778.               ParamNameAndType[Length(sSender) + 1] := char(Length(sObject));
  779.               Move(sObject[1], ParamNameAndType[Length(sSender) + 2],
  780.                 Length(sObject));
  781.             end;
  782.             Method := TFormDesigner(Designer).CreateMethod(MethodName, TypeData);
  783.             Method.Data := OwnerForm;
  784.           finally
  785.             FreeMem(TypeData, SizeOf(TTypeData));
  786.           end;
  787.           Btn.OnClick := TNotifyEvent(Method);
  788.           Designer.Modified;
  789.         end;
  790.         if (MethodName <> '') and TFormDesigner(Designer).MethodExists(MethodName) then
  791.           TFormDesigner(Designer).ShowMethod(MethodName);
  792.         Break;
  793.       end;
  794.     end;
  795.   finally
  796.     Candidates.Free;
  797.   end;
  798. end;
  799.  
  800. procedure TSpeedbarEditor.ButtonsListMouseDown(Sender: TObject;
  801.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  802. var
  803.   Item: TSpeedItem;
  804. begin
  805.   if (X < FBar.BtnWidth + 2) and (Button = mbLeft) then
  806.   begin
  807.     Item := ItemByRow(ButtonsList.Row);
  808.     if Item <> nil then begin
  809.       FDrag := True;
  810.       if Item.Visible then FDragItem := nil
  811.       else begin
  812.         FDragItem := Item;
  813.         if FButton = nil then begin
  814.           FButton := TBtnControl.Create(Self);
  815.           TBtnControl(FButton).AssignSpeedItem(Item);
  816.         end;
  817.       end;
  818.     end;
  819.   end;
  820. end;
  821.  
  822. procedure TSpeedbarEditor.ButtonsListMouseMove(Sender: TObject;
  823.   Shift: TShiftState; X, Y: Integer);
  824. var
  825.   P: TPoint;
  826. begin
  827.   if FDrag and (FButton <> nil) and (FDragItem <> nil) then begin
  828.     P := (Sender as TControl).ClientToScreen(Point(X, Y));
  829.     X := P.X - (FButton.Width {div 2});
  830.     Y := P.Y - (FButton.Height {div 2});
  831.     FButton.Activate(Bounds(X, Y, FBar.BtnWidth, FBar.BtnHeight));
  832.   end
  833.   else if FDrag then SetCursor(Screen.Cursors[crNoDrop]);
  834. end;
  835.  
  836. procedure TSpeedbarEditor.ButtonsListMouseUp(Sender: TObject;
  837.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  838. var
  839.   P: TPoint;
  840. begin
  841.   if FDrag and (Button = mbLeft) then
  842.   try
  843.     if (FDragItem <> nil) and (FButton <> nil) then begin
  844.       Dec(X, FButton.Width {div 2});
  845.       Dec(Y, FButton.Height {div 2});
  846.       P := (Sender as TControl).ClientToScreen(Point(X, Y));
  847.       FButton.Free;
  848.       FButton := nil;
  849.       if CheckSpeedBar and (FBar = FindSpeedBar(P)) then begin
  850.         P := FBar.ScreenToClient(P);
  851.         if FBar.AcceptDropItem(FDragItem, P.X, P.Y) then begin
  852.           Designer.Modified;
  853.         end;
  854.       end;
  855.     end
  856.     else SetCursor(Screen.Cursors[ButtonsList.Cursor]);
  857.   finally
  858.     FDrag := False;
  859.     FDragItem := nil;
  860.   end;
  861. end;
  862.  
  863. procedure TSpeedbarEditor.ButtonsListSelectCell(Sender: TObject; Col,
  864.   Row: Longint; var CanSelect: Boolean);
  865. var
  866.   Item: TSpeedItem;
  867. begin
  868.   Item := ItemByRow(Row);
  869.   CanSelect := not FDrag and (Item <> nil);
  870.   if FLocked = 0 then begin
  871.     if CanSelect then begin
  872.       UpdateEnabled(Row, SectionList.Row);
  873.       SelectButton(CurrentSection, Item, False);
  874.     end
  875.     else if not FDrag then begin
  876.       UpdateEnabled(-1, SectionList.Row);
  877.       SelectButton(-1, nil, True);
  878.     end;
  879.   end;
  880. end;
  881.  
  882. procedure TSpeedbarEditor.FormCreate(Sender: TObject);
  883. begin
  884.   FImage := TButtonImage.Create;
  885.   FButton := nil;
  886.   FBar := nil;
  887.   FDrag := False;
  888.   if NewStyleControls then Font.Style := [];
  889.   with FormPlacement1 do begin
  890.     UseRegistry := True;
  891.     IniFileName := SDelphiKey;
  892.   end;
  893. end;
  894.  
  895. procedure TSpeedbarEditor.FormDestroy(Sender: TObject);
  896. begin
  897.   FImage.Free;
  898. end;
  899.  
  900. procedure TSpeedbarEditor.FormClose(Sender: TObject; var Action: TCloseAction);
  901. begin
  902.   Action := caFree;
  903.   FButton.Free;
  904.   FButton := nil;
  905.   if FBar <> nil then begin
  906.     FBar.SetEditing(0);
  907.     SelectButton(-1, nil, True);
  908.     FBar.Invalidate;
  909.   end;
  910.   FBar := nil;
  911. end;
  912.  
  913. procedure TSpeedbarEditor.SectionNameKeyDown(Sender: TObject;
  914.   var Key: Word; Shift: TShiftState);
  915. begin
  916.   if Key = (VK_RETURN) then begin
  917.     SectionNameExit(SectionName);
  918.     Key := 0;
  919.     ActiveControl := SectionList;
  920.   end;
  921. end;
  922.  
  923. procedure TSpeedbarEditor.ButtonsListDrawCell(Sender: TObject; Col,
  924.   Row: Longint; Rect: TRect; State: TGridDrawState);
  925. var
  926.   I: Integer;
  927. begin
  928.   I := CurrentSection;
  929.   if (I >= 0) and (Row < FBar.ItemsCount(I)) then
  930.     DrawCellButton(Sender as TDrawGrid, Rect, ItemByRow(Row), FImage
  931.       {$IFDEF RX_D4}, TDrawGrid(Sender).IsRightToLeft {$ENDIF});
  932. end;
  933.  
  934. procedure TSpeedbarEditor.SectionListMouseDown(Sender: TObject;
  935.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  936. var
  937.   ACol, ARow: Longint;
  938. begin
  939.   if (Button = mbLeft) then
  940.     with (Sender as TDrawGrid) do begin
  941.       MouseToCell(X, Y, ACol, ARow);
  942.       Tag := Row;
  943.       BeginDrag(False);
  944.     end;
  945. end;
  946.  
  947. procedure TSpeedbarEditor.SectionListDragDrop(Sender, Source: TObject; X,
  948.   Y: Integer);
  949. var
  950.   Col, Row: Longint;
  951. begin
  952.   try
  953.     (Sender as TDrawGrid).MouseToCell(X, Y, Col, Row);
  954.     FBar.Sections[(Sender as TDrawGrid).Tag].Index := Row;
  955.     Designer.Modified;
  956.     UpdateData;
  957.     SectionList.Row := Row;
  958.   finally
  959.     (Sender as TDrawGrid).Tag := 0;
  960.   end;
  961. end;
  962.  
  963. procedure TSpeedbarEditor.SectionListDragOver(Sender, Source: TObject; X,
  964.   Y: Integer; State: TDragState; var Accept: Boolean);
  965. var
  966.   Col, Row: Longint;
  967. begin
  968.   (Sender as TDrawGrid).MouseToCell(X, Y, Col, Row);
  969.   Accept := (Row >= 0) and (Row <> (Sender as TDrawGrid).Tag);
  970. end;
  971.  
  972. procedure TSpeedbarEditor.FormShow(Sender: TObject);
  973. begin
  974.   if FBar <> nil then UpdateListHeight;
  975.   SectionList.DefaultColWidth := SectionList.ClientWidth;
  976.   ButtonsList.DefaultColWidth := ButtonsList.ClientWidth;
  977. end;
  978.  
  979. end.